# 内核安全处理

# +------------------------------------------------------------------------+
# |      权限表                                                             |
# +------------------------------------------------------------------------+
# |https://gitee.com/cxy_kevin/micronorth/wikis/开发者说明/权限表            |
# +========================================================================+
# |      函数表                                                             |
# +------------------------------------------------------------------------+
# |https://gitee.com/cxy_kevin/micronorth/wikis/开发者说明/内核安全模块-函数表|
# +------------------------------------------------------------------------+


filePath="/storage/data"                                     # 用户根文件目录
systemPath="/storage/system"                                 # 系统文件目录
appPath="/storage/data/NorthStar/data"                       # 应用目录
appfilePath="/NorthStar"                                     # 系统保留目录（相对）
permissionsConfig="/storage/system/config/permissions.cfg"   # 配置文件

class PermissionsError(Exception):
    def __init__(self, iid, string):
        self.iid=iid;
        self.string=string;
    def __str__(self):
        return '['+str(self.iid)+'] '+self.string+''
def pathCanRead(path, appname): # 判断目录是否可访问
    path = path.replace("./","") # 删除多余 './'
    if(".." in path): # 避免越权访问
        raise PermissionsError(1,"路径中不能含有 '..' (The path cannot contain '..')") 
    path=path.replace("\\","/") # 处理windows风格的路径（不推荐）
    with open(permissionsConfig,"r") as file:
        pm = eval(file.read())[appname]["files"]
    rpath=None
    if len(path)==0: # 对于空目录默认认为是软件目录
        rpath=appPath+'/'+appname
    elif(path[0]=='/'): # 根目录
        if pm<2: # 权限判断
            raise PermissionsError(0,"权限错误，没有对 '/' 访问的权限 (Permission error, no permission for '/' access)")
        if (appfilePath in path) and pm<3: # 防止应用串门
            raise PermissionsError(0,"权限错误，没有对 'NorthStar' 访问的权限 (Permission error, no permission for 'NorthStar' access)")
        rpath=filePath+path
    elif(path[0]=='~'): # 系统目录
        if pm<3: # 权限判断
            raise PermissionsError(0,"权限错误，没有对 'system' 分区访问的权限 (Permission error, no permission for 'system' part access)")
        rpath=systemPath+path[2:]
    else: # 程序文件目录
        if pm<1: # 权限判断
            raise PermissionsError(0,"权限错误，没有对 'appdata' 访问的权限 (Permission error, no permission for 'appdata' access)")
        rpath=appPath+'/'+appname+"/"+path
    return rpath

def s_open(path, mode="r", buffering=0, appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return open(rpath, mode) # 调用系统函数
def s_mkdir(path, mode="", appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return __import__('os').mkdir(rpath, mode) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_rename(path1, path2, appname="com.test"):
    try:
        rpath1=pathCanRead(path1, appname)
        rpath2=pathCanRead(path2, appname)
    except:
        raise
    else:
        return __import__('os').rename(rpath1, rpath2) # 调用系统函数
def s_getcwd():
    return appPath+'/'+appname
def s_chdir(*args,**kwargs):
    raise PermissionsError(2,"因安全原因，不支持此方法 (This method is not supported for security reasons)")
def s_rmdir(path, appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return __import__('os').rmdir(rpath) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_removedirs(path, appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return __import__('os').removedirs(rpath) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_abspath(path, appname="com.test"):
    if len(path)==0: # 对于空目录默认认为是软件目录
        return appPath+'/'+appname
    elif(path[0]=='/'): # 根目录
        return path
    elif(path[0]=='~'): # 系统目录
        return path 
    else: # 程序文件目录
        return appPath+'/'+appname+"/"+path
def s_split(path, appname="com.test"):
    return __import__('os.path').split(path) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_splitext(path, appname="com.test"):
    return __import__('os.path').splitext(path) # 调用系统函数，使用 '__import__' 防止被其他应用导入os 
def s_exists(path, appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return __import__('os.path').exists(rpath) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_getsize(path, appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return __import__('os.path').getsize(rpath) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_getatime(path, appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return __import__('os.path').getatime(rpath) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_getctime(path, appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return __import__('os.path').getctime(rpath) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_getmtime(path, appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return __import__('os.path').getmtime(rpath) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_copy(path1, path2, appname="com.test"):
    try:
        rpath1=pathCanRead(path1, appname)
        rpath2=pathCanRead(path2, appname)
    except:
        raise
    else:
        return __import__('shutil').copy(rpath1,rpath2) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_copy2(path1, path2, appname="com.test"):
    try:
        rpath1=pathCanRead(path1, appname)
        rpath2=pathCanRead(path2, appname)
    except:
        raise
    else:
        return __import__('shutil').copy2(rpath1,rpath2) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_copyfile(path1, path2, appname="com.test"):
    try:
        rpath1=pathCanRead(path1, appname)
        rpath2=pathCanRead(path2, appname)
    except:
        raise
    else:
        return __import__('shutil').copyfile(rpath1,rpath2) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_copytree(path1, path2, appname="com.test"):
    try:
        rpath1=pathCanRead(path1, appname)
        rpath2=pathCanRead(path2, appname)
    except:
        raise
    else:
        return __import__('shutil').copytree(rpath1,rpath2) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_rmtree(path, appname="com.test"):
    try:
        rpath=pathCanRead(path, appname)
    except:
        raise
    else:
        return __import__('shutil').rmtree(rpath) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
def s_move(path1, path2, appname="com.test"):
    try:
        rpath1=pathCanRead(path1, appname)
        rpath2=pathCanRead(path2, appname)
    except:
        raise
    else:
        return __import__('shutil').move(rpath1,rpath2) # 调用系统函数，使用 '__import__' 防止被其他应用导入os
    
    
class s_ble():
    # 判断权限
    def __init__(appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["bluetooth"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对蓝牙访问的权限 (Permission error, no permission for bluetooth)")
        return __import__('bluetooth').BLE() # 这是个构造函数，没有参数
    def UUID(value,appname="com.test"):
        return __import__('bluetooth').UUID(value)
    
    
def s_reset(appname="com.test"):
    # 判断权限
    with open(permissionsConfig,"r") as file:
        pm = eval(file.read())[appname]["power"]
    if pm<1:
        raise PermissionsError(3,"权限错误，没有对电源操作访问的权限 (Permission error, no permission for power operations)")
    return __import__('machine').reset()
def s_soft_reset(appname="com.test"):
    # 判断权限
    with open(permissionsConfig,"r") as file:
        pm = eval(file.read())[appname]["power"]
    if pm<1:
        raise PermissionsError(3,"权限错误，没有对电源操作访问的权限 (Permission error, no permission for power operations)")
    return __import__('machine').soft_reset()


class s_Pin():
    # 判断权限
    def __init__(appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        return __import__('machine').Pin() # 这是个构造函数，没有参数
    IN=1
    OUT=3
    PULL_UP=2
    PULL_DOWN=1
    PULL_HOLD=4
    IRQ_FALLING=2
    IRQ_RISING=1
class s_Signal():
    # 判断权限
    def __init__(pin_obj,*args,appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        return __import__('machine').Signal(pin_obj,*args)
class s_ADC():
    # 判断权限
    def __init__(pin,appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        return __import__('machine').ADC(pin)
class s_PWM():
    # 判断权限
    def __init__(dest, freq=None, duty_u16=None, duty_ns=None,appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        pwm=__import__('machine').PWM(dest)
        pwm.init(freq, duty_u16, duty_ns)
        return pwm
class s_UART():
    # 判断权限
    def __init__(pin,baudrate=9600, bits=8, parity=None, stop=1,appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        uart=__import__('machine').UART(pin)
        uart.init(baudrate, bits, parity, stop)
        return uart
class s_SPI():
    # 判断权限
    def __init__(pin,appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        spi=__import__('machine').SPI(pin)
        return spi
    MSB=0
    LSB=1
class s_SoftSPI():
    # 判断权限
    MSB=0
    LSB=1
    def __init__(baudrate=500000, polarity=0, phase=0, bits=8, firstbit=MSB, sck=None, mosi=None, miso=None ,appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        spi=__import__('machine').SoftSPI(baudrate, polarity, phase, bits, firstbit, sck, mosi, miso)
        return spi
class s_I2C():
    # 判断权限
    def __init__(pin,scl,sda,freq=400000,appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        i2c=__import__('machine').I2C(pin,scl,sda,freq)
        return i2c
class s_SoftI2C():
    # 判断权限
    def __init__(scl,sda,freq=400000,timeout=255,appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        i2c=__import__('machine').SoftI2C(scl,sda,freq,timeout)
        return i2c
class s_I2S():
    # 判断权限
    def __init__(pid,sck=None,ws=None,sd=None,mode=None,bits=None,fmt=None,rate=None,ibuf=None,appname="com.test"):
        with open(permissionsConfig,"r") as file:
            pm = eval(file.read())[appname]["pin"]
        if pm<1:
            raise PermissionsError(3,"权限错误，没有对Pin访问的权限 (Permission error, no permission for Pin)")
        i2s=__import__('machine').I2S(pid,sck=sck,ws=ws,sd=sd,mode=mode,bits=bits,format=fmt,rate=rate,ibuf=ibuf)
        return i2s
    

def s_unique_id(): # 无需权限
    return __import__('machine').unique_id()
    
    
    